package cn.com.aiouyi.dao.impl;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.TypedQuery;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.builder.CompareToBuilder;
import org.springframework.stereotype.Repository;

import cn.com.aiouyi.dao.NavigationDao;
import cn.com.aiouyi.entity.Navigation;

/**
 * Dao - 导航
 * @author hanson
 *
 */
@Repository("navigationDaoImpl")
public class NavigationDaoImpl extends BaseDaoImpl<Navigation, Long> implements NavigationDao{

	public List<Navigation> findChildren(Navigation navigation, boolean recursive, Integer count) {
		TypedQuery<Navigation> query;
		if (recursive) {
			if (navigation != null) {
				String jpql = "select obj from Navigation obj where obj.treePath like :treePath order by obj.grade asc, obj.seq asc";
				query = entityManager.createQuery(jpql, Navigation.class).setParameter("treePath", "%" + Navigation.TREE_PATH_SEPARATOR + navigation.getId() + Navigation.TREE_PATH_SEPARATOR + "%");
			} else {
				String jpql = "select obj from Navigation obj order by obj.grade asc, obj.seq asc";
				query = entityManager.createQuery(jpql, Navigation.class);
			}
			if (count != null) {
				query.setMaxResults(count);
			}
			List<Navigation> result = query.getResultList();
			sort(result);
			return result;
		} else {
			String jpql = "select obj from Navigation obj where obj.parent = :parent order by obj.seq asc";
			query = entityManager.createQuery(jpql, Navigation.class).setParameter("parent", navigation);
			if (count != null) {
				query.setMaxResults(count);
			}
			return query.getResultList();
		}
	}

	/**
	 * 排序导航
	 * @param navigations
	 */
	private void sort(List<Navigation> navigations) {
		if (CollectionUtils.isEmpty(navigations)) {
			return;
		}
		final Map<Long, Integer> orderMap = new HashMap<Long, Integer>();
		for (Navigation navigation : navigations) {
			orderMap.put(navigation.getId(), navigation.getSeq());
		}
		Collections.sort(navigations, new Comparator<Navigation>() {
			@Override
			public int compare(Navigation navigation1, Navigation navigation2) {
				Long[] ids1 = (Long[]) ArrayUtils.add(navigation1.getParentIds(), navigation1.getId());
				Long[] ids2 = (Long[]) ArrayUtils.add(navigation2.getParentIds(), navigation2.getId());
				Iterator<Long> iterator1 = Arrays.asList(ids1).iterator();
				Iterator<Long> iterator2 = Arrays.asList(ids2).iterator();
				CompareToBuilder compareToBuilder = new CompareToBuilder();
				while (iterator1.hasNext() && iterator2.hasNext()) {
					Long id1 = iterator1.next();
					Long id2 = iterator2.next();
					Integer order1 = orderMap.get(id1);
					Integer order2 = orderMap.get(id2);
					compareToBuilder.append(order1, order2).append(id1, id2);
					if (!iterator1.hasNext() || !iterator2.hasNext()) {
						compareToBuilder.append(navigation1.getGrade(), navigation2.getGrade());
					}
				}
				return compareToBuilder.toComparison();
			}
		});
	}
}
